#include<graphics.h>
#include<windows.h>
#include<iostream>
#include<conio.h>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<io.h>
#include <fstream>
#include <direct.h>
#undef UNICODE
#undef _UNICODE

#include "EasyXPng.h"
#include "GamesBuilder.h"
#include "Timer.h"
#include "HttpRequest.h"

#define HEIGHT 800
#define WIDTH 1200
#define DEBUG 0 //是否开启控制台调试信息
#pragma warning(disable:4996)
using namespace std;
#pragma comment(lib,"Winmm.lib")
#pragma once
class Entity//实体类 用来继承
{
public:
	float posx, posy, vx, vy; //实体坐标和速度 
	float height, width;	//实体的高度和宽度
	int health; //耐久
	int inRoom;	//所在的房间

	float changeX(float n);

	float changeY(float n);

	int isPassible();
};

class Block//小方块
{
public:
	int X1, X2, Y1, Y2;
};

class Box : public Entity //箱子
{
public:
	int id; //从3开始

	Box(float posx, float posy, int width, int height, int health, int inRoom, int vx, int vy, int id);

	void draw();

	void update();
};

class Drop : public Entity //凋落物
{
public:
	int id; //掉落物的id
	int visible; //是否可见
	int material;

	Drop(float posx, float posy, int width, int height, int visible, int inRoom, int vx, int vy, int material, int id);

	void update();

	void draw();
};

class Wall : public Block
{
private:
public:
	int material;

	Wall();

	Wall(int X1, int Y1, int X2, int Y2, int material);

	void draw();
};

class Room//房间类
{
private:
public:

	int id;
	int built, wallNums;//是否建造完 墙的数
	int go[5];
	vector<Wall> walls;//墙
	vector<Box> boxs;//箱子
	vector<Drop> drops;//掉落物
	int doorStatus;//门的状态 开/关
	int isMakeDrops; //是否已经放置掉落物

	Room(int id);

	void initRoom();

	void updateRoom();

	int isBuild();

	int isClear();

	void drawPosRoom();

	void showDoor();

	void showClosingDoor(int status);

	void showOpeningDoor(int status);

	Box* getBox(int id);

	void makeDrops(int nums);
};

class Map
{ //地图类
private:
public:
	int N; //房间个数
	vector<Room> rooms;

	void linkRoom(int level);

	void initMap(int level);

	Room* getRoom(int n);

	vector<Room> getRooms();


};

class Creature : public Entity
{
public:
	int numBallistic;//弹道数
	int dirction, health, healthMax; //方向，血量,血量上限
	int lastShootTime; //上次发射子弹的时间
	int shootCd; //发射CD
	int jumpCd; //跳跃CD
	int jumpMax; //最大跳跃次数
	int jumpLeft; //当前剩余跳跃次数
	int onFloor; //是否落地
	int isRemoteAttack; //是否可以远程攻击(发射子弹)
	int bulletNums; // 单次发射的子弹数量
	int shootPower; //射出子弹的威力
	int bulletlifetime; //发射出子弹的存活时间(射程);
};

class Bullet : public Entity
{
private:
public:
	IMAGE img;
	int radius, status, lifetime, power; //子弹的各属性 位置 速度 半径 是否还存活 剩余存活时间 子弹的威力
	int from;//子弹是谁打出来的 1 主角 2 怪物
	Bullet(float posx, float posy, float vx, float vy, int radius, int status, int lifetime, int from, int power);

	void draw();

	int getStatus();

	void update();

	int isCollideRocket(Creature creature);
};

class Player : public Creature
{
private:
public:
	float vy;//角色坐标的速度a
	int status; //角色状态 站立 - 1，跑动 - 2 举枪30-60度 - 3 举枪 60-90度 - 4 压枪 - 5
	int level; //当前层数
	Player(int level);

	void init();

	void draw();

	void update();

	void drawHeart();

	int addHealth(int n);
	
	int minusShootCd(int n) //减去开枪的cd
	{
		if (shootCd - n > 50) 
		{
			shootCd -= n;
			return 0;
		}
		return 1;
	}
};

class Enemy : public Creature//怪物的类
{
public:
	int kind, fly;
	Enemy(float posx, float posy, int kind, int inRoom);

	void draw();

	void update();

	void updateVelforTarge();

	void Shoot(int X1, int Y1, int X2, int Y2, int from, int power);
};

class playerData
{
public:
	char name[100];
	int totilKilled;
	int maxOnceKilled;
	int level;
	float lastTime;
	string datetime;

	playerData();

	void save();

	void updateToServer();

	int downloadFromServer();

	void clear();
};
class configData
{
public:
	configData();

	void save();

	int getEffects();

	int changeEffects();

private:
	int effects; //特效等级
};

Map maps;
const float g = 0.015;//重力加速度
const int WALL_SIZE = 10;
int tick = 1;
float posx_mouse, posy_mouse;//鼠标坐标
Player hero(1);
playerData pdata;
vector<Bullet> bullets;
vector<Enemy>monsters[233];//每个房间都有一个存怪物的vector
IMAGE heart_empty, heart_half, heart_full;//临时变量以后删 用来画血量
int serverStatus; //是否可以连接到服务器
float beginTime = clock();
int onceKilled;
int restart = 0; //用于控制是否跳出游戏
configData pcfg;

configData::configData() 
{
	std::string folderPath2 = ".\\data";
	mkdir(folderPath2.c_str()); //创建data文件夹
	if (freopen("./data/config.gm", "r", stdin)) {
		fscanf(stdin, "%d\n", &effects);
	}
	else {
		freopen("./data/config.gm", "w", stdin);
		fprintf(stdin, "%d\n", 1);
		effects = 1;
	}
	fclose(stdin);
}

int configData::getEffects() {
	return effects;
}

int configData::changeEffects() {
	effects = effects == 1 ? 2 : 1;
	return 0;
}

void configData::save() {
	freopen("./data/config.gm", "w", stdin);
	fprintf(stdin, "%d\n", effects);
	fclose(stdin);
}

playerData::playerData() {
	std::string folderPath2 = ".\\data";
	mkdir(folderPath2.c_str()); //创建data文件夹
	//读取上一次的记录
	if (freopen("./data/data.gm", "r", stdin)) {
		fscanf(stdin, "%s\n%d\n%d\n%d\n%f", &name, &totilKilled, &maxOnceKilled, &level, &lastTime);
	}
	else {
		time_t t;
		srand((unsigned)time(&t));
		string k = sti("Player_", rand() % 10000);
		freopen("./data/data.gm", "w", stdin);
		fprintf(stdin, "%s\n%d\n%d\n%d\n%f", k, 0, 0, 0, 0);
		strcpy(name, k.c_str());
		totilKilled = 0;
		maxOnceKilled = 0;
		level = 0;
		lastTime = 0;
	}
	fclose(stdin);
}

void playerData::save() {
	freopen("./data/data.gm", "w", stdin);
	fprintf(stdin, "%s\n%d\n%d\n%d\n%f", name, totilKilled, maxOnceKilled, level, lastTime);
	fclose(stdin);
}

void playerData::updateToServer() {
	if (serverStatus == 0) return;
	HttpRequest httpReq("75.119.153.85", 80);
	string que = "/game/update.php?name=";
	que += name;
	que += "&totilKilled=";
	que = sti(que, totilKilled);
	que += "&maxOnceKilled=";
	que = sti(que, maxOnceKilled);
	que += "&level=";
	que = sti(que, level);
	que += "&lastTime=";
	que = sti(que, lastTime);
	std::string res = httpReq.HttpGet(que);
	res = getContent(res);
	std::cout << res << std::endl;
}

int playerData::downloadFromServer() {
	if (serverStatus == 0) return 0;
	int flag = 0;
	HttpRequest httpReq("75.119.153.85", 80);
	string que = "/game/checkplayer.php?name=";
	que += name;
	std::string res = httpReq.HttpGet(que);
	res = getContent(res);
	int t_totilKilled, t_maxOnceKilled, t_level; //暂存服务器数据
	if (!res.empty()) {
		stringstream os;
		os << res;
		os >> name;
		os >> t_totilKilled;
		os >> t_maxOnceKilled;
		os >> t_level;
		os >> lastTime;
		//取云端和本地最大的
		if (totilKilled > t_totilKilled) {
			flag = 1;
		}
		else {
			totilKilled = t_totilKilled;
		}
		if (maxOnceKilled > t_maxOnceKilled) {
			flag = 1;
		}
		else {
			maxOnceKilled = t_maxOnceKilled;
		}
		if (level > t_level) {
			flag = 1;
		}
		else {
			level = t_level;
		}
	}
	return flag;
}

void playerData::clear() {
	strcpy(name, "");
	totilKilled = 0;
	maxOnceKilled = 0;
	level = 0;
	lastTime = 0;
}

float Entity::changeX(float n) //x坐标的变动 能动返回1 否则返回0
{
	posx += n;
	int k = isPassible();
	if (k != 1)
	{ //判断是否合法
		posx -= n;
		return k;
	}
	return 1;
}

float Entity::changeY(float n) //y坐标的变动 能动返回1 否则返回0
{
	posy += n;
	int k = isPassible();
	if (k != 1)
	{ //判断是否合法
		posy -= n;
		return k;
	}
	return 1;
}

int Entity::isPassible()//生物位置变动后是否合法（不和墙相交就是合法）
{
	Room* k = maps.getRoom(inRoom); //获取房间
	for (auto it = k->walls.begin(); it != k->walls.end(); it++) { //迭代所有的墙
		if (collisionBetweenEntity(posx, posy - height,
			posx + width, posy,
			it->X1, it->Y1,
			it->X2, it->Y2)) return 0; //有交界返回0
	}
	for (auto it = k->boxs.begin(); it != k->boxs.end(); it++) { //迭代所有的箱子
		if (&it->posx == &posx) continue; //如果posx的地址相同 -> 同一个箱子，跳过判断
		if (it->health <= 0) continue; //被打爆的箱子跳过判断
		if (collisionBetweenEntity(posx, posy - height,
			posx + width, posy,
			it->posx, it->posy - it->height,
			it->posx + it->width, it->posy)) return it->id; //有交界返回3
	}
	if (!k->isClear()) { //有怪的时候阻止走出房间
		if (posx < 0 || posx > WIDTH - 80) {
			return 0; //有交界返回0
		}
	}
	return 1; //可以通行返回1
}

Box::Box(float posx, float posy, int width, int height, int health, int inRoom, int vx, int vy, int id) {
	this->posx = posx;
	this->posy = posy;
	this->width = width;
	this->height = height;
	this->health = health;
	this->inRoom = inRoom;
	this->vx = vx;
	this->vy = vy;
	this->id = id;
}

void Box::draw() {
	gifCreater("box", posx, posy - height, tick, width, height, 0, 1);
}

void Box::update() {
	vy += g;
	if (changeY(vy) != 1) {
		vy = 0;
	}
}

Drop::Drop(float posx, float posy, int width, int height, int visible, int inRoom, int vx, int vy, int material, int id) {
	this->posx = posx;
	this->posy = posy;
	this->width = width;
	this->height = height;
	this->visible = visible;
	this->inRoom = inRoom;
	this->vx = vx;
	this->vy = vy;
	this->material = material;
	this->id = id;
}

void Drop::draw() {
	if (visible != 1) return;
	if (material == 1) gifCreater("drops.healthfull", posx, posy - height, tick, width, height, 0, 1);
	if (material == 2) gifCreater("drops.healthhalf", posx, posy - height, tick, width, height, 0, 1);
	if (material == 3) gifCreater("drops.healthmax", posx, posy - height, tick, width, height, 0, 1);
	if (material == 4) gifCreater("drops.numballistic", posx, posy - height, tick, width, height, 0, 1);
	if (material == 5) gifCreater("drops.bulletlifetime", posx, posy - height, tick, width, height, 0, 1);
	if (material == 6) gifCreater("drops.shootcd", posx, posy - height, tick, width, height, 0, 1);
}

void Drop::update() {
	vy += g;
	if (changeY(vy) != 1) {
		vy = 0;
	}
}

Wall::Wall(int X1, int Y1, int X2, int Y2, int material)
{
	this->X1 = X1;
	this->X2 = X2;
	this->Y1 = Y1;
	this->Y2 = Y2;
	this->material = material;
}

void Wall::draw()
{
	if (material == 1) imgBatchPrinter(1, X1, Y1, X2, Y2, 10, 10);
	if (material == 2) imgBatchPrinter(3, X1, Y1, X2, Y2, 45, 10);
	//画墙，因为直接调用会访问冲突，所以开了个函数画
}

Room::Room(int id)
{
	this->id = id;
	walls.reserve(32); //预分配内存，提速，防止溢出
	for (int i = 0; i < 4; ++i)go[i] = -1;
	doorStatus = 1;
}

void Room::initRoom() //一个房间里面造墙
{
	int d = 3;
	walls.push_back(Wall(0, 0, 1200, 10, 1)); //天花板
	walls.push_back(Wall(0, 790, 1200, 800, 1)); //地板
	walls.push_back(Wall(0, 200, 40, 600, 1)); //左
	walls.push_back(Wall(1160, 200, 1200, 600, 1)); //右
	if (go[0] < 0) walls.push_back(Wall(0, 0, 40, 600, 1));//左上
	if (go[1] < 0) walls.push_back(Wall(0, 200, 40, 800, 1));//左下
	if (go[2] < 0) walls.push_back(Wall(1160, 0, 1200, 600, 1));//右上
	if (go[3] < 0) walls.push_back(Wall(1160, 200, 1200, 800, 1));//右下


	for (int i = 120; i < 600; i += (rand() % 50) + 100)//随机造一些墙
	{
		int t = (rand() % 4) + 1;
		while (t--)
		{
			int j = (rand() % 700) + 100;
			int l = 90 + (rand() % 5) * 45;
			if (500 < j && j < 700 && 350 < i && i < 450) {
				continue;
			}
			if (rand() % 3 == 2) {
				boxs.push_back(Box(j + (rand() % l), i - 10, 30, 30, 4, id, 0, 0, d));
				d++;
			}
			walls.push_back(Wall(j, i, j + l, i + 10, 2));
			j += (rand() % 100) + 100;
		}
	}
	built = 1;
	isMakeDrops = 0;
}
float BGX[2333], BGY[2333], BGR[2333];
void drawBackGround()//画背景
{
	static int finish = 0, numStar = 0;
	if (finish == 0)
	{
		numStar = 300;
		for (int i = 1; i <= numStar; ++i)
		{
			BGX[i] = rand() % 1200;
			BGY[i] = rand() % 800;
			BGR[i] = rand() % 2 + 1;
		}
		finish = 1;
	}
	for (int i = 1; i <= numStar; ++i)
	{
		//setfillcolor(RGB(0,0,0));
		setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255));
		solidcircle(BGX[i], BGY[i], 1);
	}
}


void Room::updateRoom()
{ //更新房间
	if (pcfg.getEffects() == 2) drawBackGround();
	drawPosRoom();
	for (auto it = walls.begin(); it != walls.end(); it++)
	{ //把房间里的墙全部画出来
		it->draw();
	}

	for (auto it = drops.begin(); it != drops.end(); it++) {
		it->update();
		it->draw();
	}

	if (!isClear()) {
		if (doorStatus < 120) {
			doorStatus++;
			showClosingDoor(doorStatus / 20);

		}
		else {
			showDoor();
		}
	}
	else {
		if (doorStatus >= 120 && doorStatus < 240) {
			showOpeningDoor(doorStatus / 20);
			doorStatus++;
		}
	}
	if (isClear() && isMakeDrops == 0)
	{
		if (rand() % 2 == 0)
		{
			makeDrops(1);
			makeDrops(1);
			makeDrops(1);
		}
		isMakeDrops = 1;
	}
}

int Room::isBuild()
{ //获取是否初始化完毕
	return  built;
}

int Room::isClear()
{
	return monsters[id].size() == 0;
}

void Room::drawPosRoom()//画当前房间编号
{
	LOGFONT f;
	TCHAR s[20];
	_stprintf(s, _T("%d"), id + 1);
	gettextstyle(&f);						// 获取当前字体设置
	f.lfHeight = 100;						// 设置字体高度
	_tcscpy(f.lfFaceName, _T("SansTaiNa"));
	/*settextcolor(HSVtoRGB(bk_color,0.8,0.8));*/
	settextstyle(&f);
	outtextxy(550, 350, s);
}

void Room::showClosingDoor(int status)
{
	if (go[0] >= 0) gifCreater("door.gif.close", 1, 20, status, 40, 180, 0, 1);
	if (go[1] >= 0) gifCreater("door.gif.close", 1, HEIGHT - 190, status, 40, 180, 0, 1);
	if (go[2] >= 0) gifCreater("door.gif.close", WIDTH - 40, 20, status, 40, 180, 0, 1);
	if (go[3] >= 0) gifCreater("door.gif.close", WIDTH - 40, HEIGHT - 190, status, 40, 180, 0, 1);
}

void Room::showOpeningDoor(int status)
{
	if (go[0] >= 0) gifCreater("door.gif.open", 1, 20, status, 40, 180, 0, 1);
	if (go[1] >= 0) gifCreater("door.gif.open", 1, HEIGHT - 190, status, 40, 180, 0, 1);
	if (go[2] >= 0) gifCreater("door.gif.open", WIDTH - 40, 20, status, 40, 180, 0, 1);
	if (go[3] >= 0) gifCreater("door.gif.open", WIDTH - 40, HEIGHT - 190, status, 40, 180, 0, 1);
}

void Room::showDoor()
{
	if (go[0] >= 0) gifCreater("door.close", 1, 20, tick, 40, 180, 0, 1);
	if (go[1] >= 0) gifCreater("door.close", 1, HEIGHT - 190, tick, 40, 180, 0, 1);
	if (go[2] >= 0) gifCreater("door.close", WIDTH - 40, 20, tick, 40, 180, 0, 1);
	if (go[3] >= 0) gifCreater("door.close", WIDTH - 40, HEIGHT - 190, tick, 40, 180, 0, 1);
}

Box* Room::getBox(int id)
{
	if (id < 3) return NULL;
	return &boxs[id - 3];
}

void Room::makeDrops(int nums)//生成凋落物 和生成怪物同理
{
	for (int j = 1; j <= nums; ++j)
	{
		Drop now(rand() % (WIDTH - 100) + 50, rand() % HEIGHT, 30, 30, 1, id, 0, 0, 1, j);
		Drop tmp(rand() % (WIDTH - 100) + 50, rand() % HEIGHT, 30, 30, 1, id, 0, 0, 1, j);
		while (1)
		{
			Drop tmp(rand() % (WIDTH - 100) + 50, rand() % HEIGHT, 30, 30, 1, id, 0, 0, rand() % 6 + 1, j);
			if (tmp.isPassible() == 1)
			{
				now = tmp;
				break;
			}
		}
		drops.push_back(now);
	}
}

void Map::linkRoom(int level)//连接房间
{
	rooms.reserve(32);
	N = rand() % 3 + 2 + level;
	Room r(0); rooms.push_back(r);
	for (int i = 1, to, ok; i < N; ++i)//生成一棵树
	{
		ok = 0; Room r(i);
		while (1)
		{
			to = rand() % i;
			for (int j = 0; j < 4; ++j)
				if (rooms[to].go[j] == -1)
				{
					ok = 1;
					rooms[to].go[j] = i;
					r.go[3 - j] = to;
					break;
				}
			if (ok)break;
		}
		rooms.push_back(r);
	}
	for (int i = 0; i < N; ++i)rooms[i].initRoom();
}

void Map::initMap(int level)//地图生成器 
{
	srand(time(0));
	rooms.clear();
	linkRoom(level);
}

Room* Map::getRoom(int n)
{ //根据id获取房间的实体
	if (n > N - 1 || n < 0)
	{
		return NULL;
	}
	else
	{
		return &rooms[n];
	}
}

vector<Room> Map::getRooms()
{ //返回所有的房间
	return rooms;
}

void Enemy::Shoot(int X1, int Y1, int X2, int Y2, int from, int power)
{
	if (isRemoteAttack && clock() - lastShootTime > shootCd)
	{
		if (kind == 2) {
			float tmpX = X1 + width / 2, tmpY = Y1 - height / 2; //计算子弹的各个属性
			float differenceX = X2 - tmpX, differenceY = Y2 - tmpY;
			Bullet k(tmpX, tmpY, differenceX / sqrt(differenceX * differenceX + differenceY * differenceY), differenceY / sqrt(differenceX * differenceX + differenceY * differenceY), 10, 1, bulletlifetime, from, power);
			bullets.push_back(k);
		}
		if (kind == 3) {
			float tmpX = X1 + width / 2, tmpY = Y1 - height / 2;
			Bullet k(tmpX, tmpY, 0, 1, 10, 1, bulletlifetime, from, power);
			bullets.push_back(k);
		}
		lastShootTime = clock();
	}
}

Bullet::Bullet(float posx, float posy, float vx, float vy, int radius, int status, int lifetime, int from, int power)
{
	this->posx = posx;
	this->posy = posy;
	this->vx = vx;
	this->vy = vy;
	this->radius = radius;
	this->status = status;
	this->lifetime = lifetime;
	this->from = from;
	this->power = power;
	loadimage(&img, _T(".\\img\\material\\bullet\\bullet.png"), 2 * radius, 2 * radius);
}

void Bullet::draw()
{
	if (posx < 0 || posx > WIDTH || posy < 0 || posy > HEIGHT || lifetime <= 0)//如果子弹出界了就删去
	{
		status = 0;
	}
	if (status == 1)//否则画出来
	{
		if (from == 1) {
			gifCreater("bullet.hero", posx, posy - 2 * radius, tick, 2 * radius, 2 * radius, 0, 0.1);
		}
		if (from == 2) {
			gifCreater("bullet.enemy", posx, posy - 2 * radius, tick, 2 * radius, 2 * radius, 0, 0.1);
		}
		lifetime--;
	}
}

int Bullet::getStatus() //获取子弹状态
{
	return status;
}

void Bullet::update() //更新子弹坐标
{
	posx += vx;
	posy += vy;
}

int Bullet::isCollideRocket(Creature creature) // 判断生物是否和子弹碰撞
{
	float distance_x = abs(creature.posx - posx);
	float distance_y = abs(creature.posy - posy);

	if (collisionBetweenEntity(posx, posy - 2 * radius, posx + 2 * radius, posy, creature.posx, creature.posy - creature.height, creature.posx + creature.width, creature.posy))return 1;
	else return 0;
}

Player::Player(int level)
{
	this->level = level;
}

void Player::init()
{
	this->height = 80;
	this->width = 64;
	this->posx = WIDTH / 2 - hero.width / 2;
	this->posy = 770;
	this->healthMax = 6;
	this->health = 6;
	this->shootCd = 500;
	this->jumpMax = 2;
	this->isRemoteAttack = 1;
	this->bulletNums = 1;
	this->shootPower = 1;
	this->numBallistic = 1;//弹道数
	this->bulletlifetime = 100;
	status = 1;
	jumpLeft = jumpMax;
	vy = 0;
	jumpCd = 200;
	int level = 1;
}

void Player::draw() //根据状态返回对应的贴图
{
	if (status == 1)gifCreater("hero.stay", posx, posy - height, tick, width, height, dirction, 0.02);
	if (status == 2)gifCreater("hero.run", posx, posy - height, tick, width, height, dirction, 0.02);
	if (status == 3)gifCreater("hero.shoot.up_30_60", posx, posy - height, tick, width, height, dirction, 0.02);
	if (status == 4)gifCreater("hero.shoot.up_60_90", posx, posy - height, tick, width, height, dirction, 0.02);
	if (status == 5)gifCreater("hero.shoot.down", posx, posy - height, tick, width, height, dirction, 0.02);

	drawHeart(); //画血量ui
}

int Player::addHealth(int n) //回血
{
	if (health + n > healthMax) 
	{
		int k = health + n - healthMax;
		health = healthMax;
		return k;
	}
	else {
		health += n;
	}
	return 0;
}


void Player::update()
{
	vy += g;
	if (changeY(vy) != 1)
	{
		if (vy > 0)
		{
			jumpLeft = jumpMax;
		}
		vy = 0;
	}

	if (posx + width - 30 < 0)//向左进入其他房间
	{
		int toRoom;
		if (posy <= 400)//左上角
		{
			toRoom = maps.getRoom(inRoom)->go[0];
		}
		else//左下角
		{
			toRoom = maps.getRoom(inRoom)->go[1];
		}
		for (int i = 0; i < 4; i++)
		{
			if (maps.getRoom(toRoom)->go[i] == inRoom) //找到传送过去是哪个门
			{
				posx = posTransformCoordinate(1, i, width);//位置转坐标
				posy = posTransformCoordinate(2, i, width);//位置转坐标
				inRoom = toRoom;
			}
		}
		bullets.clear();//进入其他房间就把子弹全清空
	}
	if (posx + width - 30 > WIDTH)//向右进入其他房间
	{
		int toRoom;
		if (posy <= 400)//右上角
		{
			toRoom = maps.getRoom(inRoom)->go[2];
		}
		else//右下角
		{
			toRoom = maps.getRoom(inRoom)->go[3];
		}
		for (int i = 0; i < 4; i++)
		{
			if (maps.getRoom(toRoom)->go[i] == inRoom)
			{ //找到传送过去是哪个门
				posx = posTransformCoordinate(1, i, width);//位置转坐标
				posy = posTransformCoordinate(2, i, width);//位置转坐标
				inRoom = toRoom;
			}
		}
		bullets.clear();//进入其他房间就把子弹全清空
	}
	Room* k = maps.getRoom(inRoom);
	for (auto it = k->drops.begin(); it != k->drops.end(); it++) 
	{ //迭代所有的掉落物
		if (&it->posx == &posx) continue; //如果posx的地址相同 -> 同一个掉落物，跳过判断
		if (it->visible <= 0) continue; //被打爆的箱子跳过判断
		if (collisionBetweenEntity(posx, posy - height,
			posx + width, posy,
			it->posx, it->posy - it->height,
			it->posx + it->width, it->posy))//判断凋落物是哪种类型
		{
			if (it->material == 1)//回血2点
			{
				int k = addHealth(2);
				if (k == 0) {
					it->visible = 0;
				}
				if (k == 1) {
					it->material = 2;
				}
			}
			if (it->material == 2)//回血1点
			{
				int k = addHealth(1);
				if (k == 0) {
					it->visible = 0;
				}
			}
			if (it->material == 3) {//加血量上限
				healthMax += 2;
				it->visible = 0;
			}
			if (it->material == 4) {//加弹道数
				numBallistic += 1;
				it->visible = 0;

			}
			if (it->material == 5) {//加子弹飞行时间
				bulletlifetime += 50;
				it->visible = 0;
			}
			if (it->material == 6) {//减少开枪cd
				minusShootCd(50);
				shootCd -= 50;
				shootCd = max(shootCd ,100);
				it->visible = 0;
			}
		}
	}
}

void Player::drawHeart()//画角色血量
{
	int nowx = 10;
	for (int i = 1; i <= health / 2; ++i)putimagePng(nowx, 20, &heart_full), nowx += 50;
	if (health & 1/*奇数额外画半颗心*/)putimagePng(nowx, 20, &heart_half), nowx += 50;
	for (int i = 1; i <= (healthMax - health) / 2; ++i)putimagePng(nowx, 20, &heart_empty), nowx += 50;
}

Enemy::Enemy(float posx, float posy, int kind, int inRoom)
{
	this->posx = posx;
	this->posy = posy;
	this->vx = 0;
	this->vy = 10;
	this->kind = kind;
	this->inRoom = inRoom;
	this->bulletlifetime = 20000;
	onFloor = 0;
	if (kind == 1)//每种怪物的属性
	{
		health = 2; width = 40; height = 40; fly = 0;
		shootCd = -1;
		isRemoteAttack = 0;
		bulletNums = 0;
	}
	if (kind == 2)//每种怪物的属性
	{
		health = 3; width = 60; height = 60; fly = 1;
		shootCd = 1000;
		isRemoteAttack = 1;
		bulletNums = 1;
	}
	if (kind == 3)//每种怪物的属性
	{
		this->posy = (int)posy % 300 + 30;
		health = 3; width = 70; height = 64; fly = 1;
		shootCd = 800;
		isRemoteAttack = 1;
		bulletNums = 1;
		vx = 0.5;
	}
}

void Enemy::draw()//画怪物
{
	if (kind == 1)
	{
		if (health > 0) gifCreater("nutscrab.run", posx, posy - 37, tick, width, height, dirction, 0.02);
	}
	if (kind == 2)
	{
		if (health > 0)
		{
			gifCreater("nutssnake.fly", posx, posy - 37, tick, width, height, dirction, 0.02);
		}
	}
	if (kind == 3)
	{
		if (health > 0)
		{
			gifCreater("nutsjellyfish.fly", posx, posy - 37, tick, width, height, 0, 0.02);
		}
	}
}

void Enemy::update()
{
	//vx == 0 时不做修改
	if (vx > 0)//确定方向
	{
		dirction = 0;
	}
	if (vx < 0)//确定方向
	{
		dirction = 1;
	}
	if (fly)
	{
		if (kind == 2) 
		{
			updateVelforTarge();
			posx += vx;
			posy += vy;
		}
		if (kind == 3) {
			;
			posx += vx;
			if (posx < 40 || posx > WIDTH - width - 30) 
			{
				vx = -vx;
			}
		}
	}
	else
	{
		vy = 5;
		if (!onFloor)//判断是否已经落地
		{
			if (changeY(vy) != 1)
			{
				onFloor = 1;
				vx = 0.5;
			}
		}
		else
		{
			if (changeY(vy) == 1)
			{
				changeY(-vy);
				vx = -vx;
			}
		}
		if (changeX(vx) != 1 || posx < 0 || posx > WIDTH) {
			vx = -vx;
		}
	}
	if (isRemoteAttack)//会发子弹的怪
	{
		Shoot(posx, posy, hero.posx, hero.posy, 2, 1);
	}
}

void Enemy::updateVelforTarge() // 让会飞的怪的速度瞄向角色
{
	if (hero.posx > posx) vx = 0.5;// 目标在怪左边，怪x方向速度向右
	else if (hero.posx < posx) vx = -0.5;// 目标在怪右边，怪x方向速度向左
	if (hero.posy > posy)vy = 0.5; // 目标在怪下方，怪y方向速度向下
	else if (hero.posy < posy)vy = -0.5; // 目标在怪上方，怪y方向速度向上
}

int sumMonster;
void makeMonster()//怪物生成器
{
	sumMonster = 0;
	for (int i = 1; i < maps.N; ++i)
	{
		int numMonster = rand() % 2 + hero.level;//确定怪物数量
		sumMonster += numMonster;
		for (int j = 1; j <= numMonster; ++j)
		{
			Enemy now(rand() % 400 + 400, rand() % HEIGHT, (rand() % 3) + 1, i);//随机坐标
			while (1)
			{
				Enemy tmp(rand() % 400 + 400, rand() % HEIGHT, (rand() % 3) + 1, i);//随机坐标
				if (tmp.isPassible() == 1)//直到怪物和墙不重合为止
				{
					now = tmp;
					break;
				}
			}
			monsters[i].push_back(now);
		}
	}
}



void Init()//预处理
{
	maps.initMap(hero.level);//初始化
	cleardevice();
	if (hero.level == 1)
	{
		beginTime = clock();
		onceKilled = 0;//单次击杀
		hero.init();//角色初始化大小和坐标和血量
		maps.initMap(1);//地图初始化
		bullets.clear();
	}
	else
	{
		hero.posx = WIDTH / 2 - hero.width / 2;
		hero.posy = 770;
	}
	hero.inRoom = 0;//初始房间是0号
	for (int i = 0; i < maps.N; i++)
	{
		monsters[i].clear();
	}
	makeMonster();//造怪物
}

void drawMonster()//画怪物
{
	int nowRoom = hero.inRoom;
	for (vector<Enemy>::iterator it = monsters[nowRoom].begin(); it != monsters[nowRoom].end(); ++it) it->draw();
}

void drawBullet()//画子弹
{
	for (auto it = bullets.begin(); it != bullets.end(); it++) it->draw();
}

void drawDeath()//画死亡界面
{
	mciSendString(_T("close shootMusic"), NULL, 0, NULL);//关音乐
	mciSendString(_T("close jumpMusic"), NULL, 0, NULL);//关音乐

	mciSendString(_T("close deathMusic"), NULL, 0, NULL);
	mciSendString(_T("open .\\music\\death.mp3 alias deathMusic"), NULL, 0, NULL);//打开失败音效
	mciSendString(_T("play deathMusic"), NULL, 0, NULL);
	while (1)
	{
		BeginBatchDraw();
		setbkmode(TRANSPARENT);
		settextcolor(RGB(255, 0, 0));
		settextstyle(120, 0, _T("宋体"));
		outtextxy(400, 350, _T("游戏失败"));
		FlushBatchDraw();
		cin.clear();
		char k = 'f';
		k = getch();
		if (k == '\r') //按回车重新开始
		{
			restart = 1;
			break;
		}
	}
}
void drawWin()//画胜利界面
{
	mciSendString(_T("close winMusic"), NULL, 0, NULL);
	mciSendString(_T("open .\\music\\win.mp3 alias winMusic"), NULL, 0, NULL);//打开胜利音效
	mciSendString(_T("play winMusic"), NULL, 0, NULL);
	while (1)
	{
		mciSendString(_T("close shootMusic"), NULL, 0, NULL);
		BeginBatchDraw();
		setbkmode(TRANSPARENT);
		settextcolor(RGB(255, 0, 0));
		settextstyle(120, 0, _T("宋体"));
		outtextxy(350, 350, _T("恭喜通关本层！"));
		FlushBatchDraw();
		bullets.clear();//清空子弹
		Sleep(3000);
		if (kbhit())break;//进入下一层
	}
	hero.level++;
	Init();//再次初始化
}

void drawBox()//画箱子
{
	Room* now = maps.getRoom(hero.inRoom);
	for (auto it = now->boxs.begin(); it != now->boxs.end(); it++)
	{
		if (it->health > 0) it->draw();
	}
}

void show()//画出所有部分 
{
	cleardevice();
	BeginBatchDraw();
	maps.getRoom(hero.inRoom)->updateRoom();//房间内更新
	drawBox();//画箱子
	drawMonster();//画怪物
	drawBullet();//画子弹
	hero.draw();//画角色，位于最上的图层
	FlushBatchDraw();
}
void updateWithoutInput()
{
	tick++;
	if (tick > 0x3f3f3f3f) tick = 1;

	hero.update();//对于HERO坐标更新

	int nowRoom = hero.inRoom;//怪物坐标的更新
	Room* now = maps.getRoom(nowRoom);
	static float lastTime = 0;
	for (vector<Bullet>::iterator it1 = bullets.begin(); it1 != bullets.end();)//子弹的更新
	{
		it1->update();//子弹坐标的更新
		for (vector<Enemy>::iterator it2 = monsters[nowRoom].begin(); it2 != monsters[nowRoom].end(); ++it2)//子弹打到怪的更新
		{
			if (it1->from == 1 && it2->health > 0 && collisionBetweenEntity(it1->posx, it1->posy - 2 * it1->radius, it1->posx + 2 * it1->radius, it1->posy, it2->posx, it2->posy - it2->height, it2->posx + it2->width, it2->posy))//如果子弹碰到了怪
			{
				--it2->health;//怪物掉血
				it1->status = 0;//子弹消失
				break;
			}
		}
		for (auto it2 = now->boxs.begin(); it2 < now->boxs.end(); it2++) //子弹打箱子
		{
			if (it2->health > 0 && collisionBetweenEntity(it1->posx, it1->posy - 2 * it1->radius, it1->posx + 2 * it1->radius, it1->posy, it2->posx, it2->posy - it2->height, it2->posx + it2->width, it2->posy))//如果子弹碰到了怪
			{
				--it2->health;//箱子掉血
				it1->status = 0;//子弹消失
				break;
			}
		}
		float nowTime = clock();
		if (nowTime - lastTime > 1000 && it1->from == 2 && collisionBetweenEntity(it1->posx, it1->posy - 2 * it1->radius, it1->posx + 2 * it1->radius, it1->posy, hero.posx, hero.posy - hero.height, hero.posx + hero.width, hero.posy))//如果子弹碰到了人
		{
			lastTime = nowTime;//角色受伤后会有一段无敌时间
			hero.health--;//角色掉血
			it1->status = 0;//子弹消失
			break;
		}
		if (it1->getStatus() == 0) it1 = bullets.erase(it1);
		else ++it1;
	}
	for (auto it = now->boxs.begin(); it != now->boxs.end(); it++) //箱子坐标的更新
	{
		it->update();
	}
	for (vector<Enemy>::iterator it = monsters[nowRoom].begin(); it != monsters[nowRoom].end();)//怪物的更新
	{
		it->update();//怪物坐标的更新
		if (it->health <= 0)
		{
			it = monsters[nowRoom].erase(it);
			char k[10];
			onceKilled++;//单次击杀
			pdata.totilKilled++;//总击杀
			pdata.save();
			--sumMonster;
			if (sumMonster == 0)//本层的怪都打完了
			{
				drawWin();
				return;
			}
		}
		else ++it;
	}
	for (vector<Enemy>::iterator it = monsters[nowRoom].begin(); it != monsters[nowRoom].end(); ++it)//检测怪物是否碰到了人
	{
		float nowTime = clock();
		if (nowTime - lastTime > 1000 && collisionBetweenEntity(hero.posx, hero.posy - hero.height, hero.posx + hero.width, hero.posy, it->posx, it->posy - it->height, it->posx + it->width, it->posy))//如果子弹碰到了怪
		{//怪物碰到了人
			lastTime = nowTime;
			--hero.health;
			break;
		}
		if (hero.health <= 0)//角色死亡
		{
			if (hero.level > pdata.level) {//记录的层数
				pdata.level = hero.level;
			}
			if (hero.level == pdata.level) {//记录的层数
				pdata.lastTime = max(pdata.lastTime, clock() - beginTime);
			}
			if (onceKilled > pdata.maxOnceKilled) {//记录单次击杀
				pdata.maxOnceKilled = onceKilled;
			}
			pdata.save();
			pdata.updateToServer();
			drawDeath();//画死亡界面
			return;
		}
	}
}

void updateWithInput()
{
	int flag = 1/*判断是否奔跑，以此来更新角色状态图片*/;
	MOUSEMSG m;
	static int shoot = 0;//判断是否正在开枪
	static float lastShootTime = 0;//上次开枪时间
	static float lastJumpTime = 0;//上次跳跃时间
	if (MouseHit())//关于鼠标的操作 
	{
		m = GetMouseMsg();
		posx_mouse = m.x; posy_mouse = m.y;//鼠标位置

		if (m.uMsg == WM_LBUTTONDOWN)
		{
			shoot = 1;//开枪了
			//mciSendString(_T("open .\\music\\shoot.mp3 alias shootMusic"), NULL, 0, NULL);//打开开枪音效
			//mciSendString(_T("play shootMusic repeat"), NULL, 0, NULL);
		}
		if (m.uMsg == WM_LBUTTONUP)
		{
			/*mciSendString(_T("close shootMusic"), NULL, 0, NULL);//关闭开枪音效*/
			shoot = 0;//不开枪了
		}
		flag = 0;
	}

	if (shoot)
	{
		if (posx_mouse < hero.posx) hero.dirction = 1;/*枪口的朝向*/
		else hero.dirction = 0;
		if (abs(posx_mouse - hero.posx) < abs(posy_mouse - hero.posy)) hero.status = 4;
		else hero.status = 3;
		if (posy_mouse - hero.posy > 0) hero.status = 5;
	}

	if (shoot && clock() - lastShootTime > hero.shootCd)//按下了左键 发射子弹 调整这里的300就可以调整射速
	{//下面可以实现子弹的裂变《论学好数学的重要性》
		float tmpX = hero.posx + hero.width / 2, tmpY = hero.posy - hero.height / 2;//计算子弹的发射位置
		float jiao;
		if (abs(posx_mouse - tmpX) < 2)//垂直设计特殊处理
		{
			if (posy_mouse > tmpY)jiao = -3.1415926 / 2;
			else jiao = 3.1415926 / 2;
		}
		else//否则正常处理
		{
			if (posx_mouse > tmpX)jiao = atan((tmpY - posy_mouse) / (posx_mouse - tmpX));//找到目标点与发射点之间的角度
			else jiao = atan((tmpY - posy_mouse) / (posx_mouse - tmpX)) + 3.1415926;//这是在左边的情况
		}
		float now = jiao - 3.1415926 / 6 + 3.1415926 / 3 / (hero.numBallistic + 1);//右旋三十度
		for (int i = 1; i <= hero.numBallistic; ++i, now += 3.1415926 / 3 / (hero.numBallistic + 1))//向左旋三十度移动
		{
			Bullet k(tmpX, tmpY, 7.0 * cos(now), 7.0 * -sin(now), 10, 1, hero.bulletlifetime, 1, hero.shootPower);//添加子弹
			bullets.push_back(k);
		}
		lastShootTime = clock();
	}

	if (GetKeyState(0x41) < 0)//按下了A
	{
		int k = hero.changeX(-1);
		if (k >= 3)
		{
			if (maps.getRoom(hero.inRoom)->getBox(k)->changeX(-1) == 1)
			{
				maps.getRoom(hero.inRoom)->getBox(k)->changeX(-1);
			}
		}
		if (!shoot)hero.status = 2;
		if (flag) hero.dirction = 1;
		flag = 0;	
	}
	if (GetKeyState(0x44) < 0)//按下了D
	{
		int k = hero.changeX(1);//x坐标改变
		if (k >= 3)
		{
			if (maps.getRoom(hero.inRoom)->getBox(k)->changeX(1) == 1)
			{
				maps.getRoom(hero.inRoom)->getBox(k)->changeX(1);
			}
		}
		if (!shoot)hero.status = 2;//改变角色举枪状态
		if (flag) hero.dirction = 0;
		flag = 0;
	}
	if(GetKeyState(0x41) < 0||GetKeyState(0x44) < 0)//按下了 a 或 d
	{
		mciSendString(_T("open .\\music\\run.mp3 alias runMusic"), NULL, 0, NULL);//打开跑步音效
		mciSendString(_T("play runMusic"), NULL, 0, NULL);
	}
	else
	{
		mciSendString(_T("close runMusic"), NULL, 0, NULL);//关闭跑步音效
	}
	if (GetKeyState(0x57) < 0 && hero.jumpLeft > 0 && clock() - lastJumpTime > hero.jumpCd)//关闭跑步音效
	{
		hero.jumpLeft--;//跳跃次数减少
		hero.vy = -3;//改变速度
		lastJumpTime = clock();//记录上次跳跃的时间点

		mciSendString(_T("close jumpMusic"), NULL, 0, NULL);//打开跳跃音效
		mciSendString(_T("open .\\music\\jump.mp3 alias jumpMusic"), NULL, 0, NULL);//打开跳跃音效
		mciSendString(_T("play jumpMusic"), NULL, 0, NULL);//打开跳跃音效
	}
	if (flag && hero.status != 3 && hero.status != 4 && hero.status != 5) hero.status = 1; //没有操作，重置角色状态
}

void LoadResources() {
	IMAGE loading;//画“加载中”的画面
	loadimage(&loading, _T(".\\img\\loading.png"), 1200, 800);//画“加载中”的画面
	putimagePng(0, 0, &loading);//画“加载中”的画面
	loadimage(&heart_empty, _T(".\\img\\material\\heart\\empty.png"), 50, 50);//临时变量以后删 用来画血量
	loadimage(&heart_half, _T(".\\img\\material\\heart\\half.png"), 50, 50);//临时变量以后删 用来画血量
	loadimage(&heart_full, _T(".\\img\\material\\heart\\full.png"), 50, 50);//临时变量以后删 用来画血量
	initImg(); //记载图片
}

void showServerStatus() {
	if (serverStatus == 1) {
		setfillcolor(GREEN);
		solidcircle(1090, 780, 10);
		settextcolor(RGB(0, 238, 0));
		outtextxy(1110, 770, _T("在线模式"));
	}
	else {
		setfillcolor(RED);
		solidcircle(1090, 780, 10);
		settextcolor(RGB(165, 42, 42));
		outtextxy(1110, 770, _T("离线模式"));
	}
}

void showMenu_2() {
	int firstflash = 1; //第一次进入的时候要先显示了UI再读入，不然输入前会黑屏
	int select = 1;
	int isInput = 0;
	string name = "";
	cleardevice();
	BeginBatchDraw();
	while (1) {
		cin.clear();
		char k = 'f';
		string pri = "游戏ID:       ";
		if (firstflash == 1) {
			name = pdata.name;
			firstflash = 0;
		}
		else {
			k = getch();
		}
		if (k == 0x08) {
			if (isInput == 1 && !name.empty()) name.pop_back();
		}
		else {
			if (isInput == 1) {
				if (select == 1) {
					if (k == 'a' || k == 'A' || k == 'd' || k == 'D') {
						pcfg.changeEffects();
					}
				}
				if (select == 2) {
					if (('a' <= k && k <= 'z') || ('A' <= k && k <= 'Z') || k == '_' || k == '-') {
						name += k;
					}
				}
			}
			else {
				if (k == 'w' || k == 'W') {
					if (select > 1) {
						select--;
					}
				}
				if (k == 's' || k == 'S') {
					if (select < 3) {
						select++;
					}
				}
			}
		}
		if (k == '\r') {
			if (select == 1 || select == 2) {
				isInput = isInput == 1 ? 0 : 1;
			}
			if (select == 3) {
				pdata.clear();
				strcpy(pdata.name, name.c_str());
				pdata.downloadFromServer();
				pdata.save();
				pcfg.save();
				break;
			}
		}

		pri += name;

		gifCreater("menu.1", WIDTH / 2 - 300, 0, tick, 600, 800, 0, 1);
		showServerStatus();
		setbkmode(TRANSPARENT);
		settextstyle(20, 0, _T("宋体"), 0, 0, 800, 0, 0, 0);
		TCHAR tszWord[1024];
		char szWord[100];
		strcpy(szWord, pri.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		if (select == 1) {
			if (isInput == 1) {
				settextcolor(RGB(255, 0, 0));
			}
			else {
				settextcolor(RGB(64, 207, 235));
			}
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		if (pcfg.getEffects() == 1) {
			outtextxy(510, 390, _T("特效等级:     ◀ 低 ▶"));
		}
		else if (pcfg.getEffects() == 2) {
			outtextxy(510, 390, _T("特效等级:     ◀ 高 ▶"));
		}

		if (select == 2) {
			if (isInput == 1) {
				settextcolor(RGB(255, 0, 0));
			}
			else {
				settextcolor(RGB(64, 207, 235));
			}
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(510, 420, tszWord);
		if (select == 3) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(580, 450, _T("确认"));
		FlushBatchDraw();
	}
}

void showMenu_3() {
	int firstflash = 1; //第一次进入的时候要先显示了UI再读入，不然输入前会黑屏
	int select = 1;
	cleardevice();
	BeginBatchDraw();
	while (1) {
		cin.clear();
		if (firstflash == 1) {
			firstflash = 0;
		}
		else {
			char k = 'f';
			k = getch();
			if (k == '\r') {
				if (select == 1) {
					break;
				}
			}
		}
		gifCreater("menu.1", WIDTH / 2 - 300, 0, tick, 600, 800, 0, 1);
		showServerStatus();
		settextcolor(RGB(133, 96, 208));
		setbkmode(TRANSPARENT);
		settextstyle(20, 0, _T("宋体"), 0, 0, 800, 0, 0, 0); \
			string t;
		TCHAR tszWord[1024];
		char szWord[100];
		t = sti("总击杀数:", pdata.totilKilled);
		strcpy(szWord, t.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		outtextxy(470, 370, tszWord);
		t = sti("最高单轮击杀:", pdata.maxOnceKilled);
		strcpy(szWord, t.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		outtextxy(470, 400, tszWord);
		t = sti("最高层数:", pdata.level);
		strcpy(szWord, t.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		outtextxy(470, 430, tszWord);
		t = sti("最短用时:", (int)pdata.lastTime / 1000);
		t += "s";
		strcpy(szWord, t.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		outtextxy(470, 460, tszWord);

		if (select == 1) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(580, 500, _T("确认"));
		FlushBatchDraw();
	}
}

void showMenu_4() {
	int firstflash = 1; //第一次进入的时候要先显示了UI再读入，不然输入前会黑屏
	int select = 1;
	int from = 1;
	int isChange = 1; //改动一次范围刷新一次，否则请求次数会过多
	int to = 15;
	playerData pds[20];
	cleardevice();
	BeginBatchDraw();
	while (1) {
		cin.clear();
		if (firstflash == 1) {
			firstflash = 0;
		}
		else {
			char k = 'f';
			k = getch();
			if (k == '\r') {
				if (select == 1) {
					break;
				}
			}
			if (k == 'A' || k == 'a') {
				if (from - 15 > 0) {
					from -= 15;
					to -= 15;
					isChange = 1;
				}
			}
			if (k == 'D' || k == 'd') {
				from += 15;
				to += 15;
				isChange = 1;
			}
		}
		if (serverStatus && isChange) {
			HttpRequest httpReq("75.119.153.85", 80);
			string que = "/game/checktop.php?from=";
			que = sti(que, from);
			que += "&to=";
			que = sti(que, to);
			std::string res = httpReq.HttpGet(que);
			res = getContent(res);
			stringstream os;
			if (!res.empty()) {
				os << res;
			}
			string datetime_1, datetime_2; //在数据库里日期和时间分开了，所以读的时候要读两次
			for (int i = 0; i <= to - from; i++) {
				os >> pds[i].name;
				os >> pds[i].totilKilled;
				os >> pds[i].maxOnceKilled;
				os >> pds[i].level;
				os >> pds[i].lastTime;
				os >> datetime_1;
				os >> datetime_2;
				pds[i].datetime = datetime_1 + " " + datetime_2;
			}
			for (int i = 0; i <= to - from; i++) { //清空
				if (strcmp(pds[i].name, "") == 0) {
					strcpy(pds[i].name, "");
					pds[i].totilKilled = 0;
					pds[i].maxOnceKilled = 0;
					pds[i].level = 0;
					pds[i].lastTime = 0;
					pds[i].datetime = "";
				}
			}
			isChange = 0;
		}
		cleardevice();
		gifCreater("menu.1", WIDTH / 2 - 300, 0, tick, 600, 800, 0, 1);
		showServerStatus();
		settextcolor(RGB(133, 96, 208));
		setbkmode(TRANSPARENT);
		settextstyle(15, 0, _T("宋体"), 0, 0, 800, 0, 0, 0);
		string t;
		TCHAR tszWord[1024];
		char szWord[100];
		settextcolor(RGB(64, 207, 235));
		outtextxy(300, 320, _T("游戏ID"));
		outtextxy(420, 320, _T("总击杀数"));
		outtextxy(510, 320, _T("最高单轮击杀"));
		outtextxy(650, 320, _T("最高层数"));
		outtextxy(750, 320, _T("最短用时"));
		outtextxy(850, 320, _T("上次更新"));
		for (int i = 0; i <= to - from; i++) {
			strcpy(szWord, pds[i].name);
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(300, 350 + (i * 20), tszWord);
			t = sti("", pds[i].totilKilled);
			strcpy(szWord, t.c_str());
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(420, 350 + (i * 20), tszWord);
			t = sti("", pds[i].maxOnceKilled);
			strcpy(szWord, t.c_str());
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(510, 350 + (i * 20), tszWord);
			t = sti("", pds[i].level);
			strcpy(szWord, t.c_str());
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(650, 350 + (i * 20), tszWord);
			t = sti("", pds[i].lastTime);
			strcpy(szWord, t.c_str());
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(750, 350 + (i * 20), tszWord);
			t = pds[i].datetime;
			strcpy(szWord, t.c_str());
			MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
			outtextxy(850, 350 + (i * 20), tszWord);
		}

		if (select == 1) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}

		t = "";
		t = sti(t, from);
		t += "-";
		t = sti(t, to);
		strcpy(szWord, t.c_str());
		MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024);
		outtextxy(320, 770, tszWord);
		settextstyle(20, 0, _T("宋体"), 0, 0, 800, 0, 0, 0);
		outtextxy(850, 770, _T("确认"));
		FlushBatchDraw();
	}
}


void showMenu_1() {
	int firstflash = 1; //第一次进入的时候要先显示了UI再读入，不然输入前会黑屏
	int select = 1;
	BeginBatchDraw();
	while (1) {
		Sleep(100);
		char k = 'f';
		if (firstflash == 1) {
			firstflash = 0;
		}
		else {
			k = getch();
		}
		if (k == 'w' || k == 'W') {
			if (select > 1) {
				select--;
			}
		}
		if (k == 's' || k == 'S') {
			if (select < 5) {
				select++;
			}
		}
		if (k == 0x0D) {
			if (select == 1) {
				break;
			}
			if (select == 2) {
				showMenu_2();
			}
			if (select == 3) {
				showMenu_3();
			}
			if (select == 4) {
				showMenu_4();
			}
			if (select == 5) {
				exit(0);
			}
		}
		setbkmode(TRANSPARENT);
		settextstyle(20, 0, _T("宋体"), 0, 0, 800, 0, 0, 0);
		cleardevice();
		gifCreater("menu.1", WIDTH / 2 - 300, 0, tick, 600, 800, 0, 1);
		showServerStatus();
		if (select == 1) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(560, 400, _T("进入酒吧"));
		if (select == 2) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(560, 430, _T("游戏设置"));
		if (select == 3) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(560, 460, _T("个人成就"));
		if (select == 4) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(560, 490, _T("游戏榜单"));
		if (select == 5) {
			settextcolor(RGB(64, 207, 235));
		}
		else {
			settextcolor(RGB(133, 96, 208));
		}
		outtextxy(560, 520, _T("退出游戏"));
		FlushBatchDraw();
	}
}

void checkServerStatus() {
	HttpRequest httpReq("75.119.153.85", 80);
	string que = "/game/serverstatus.php";
	std::string res = httpReq.HttpGet(que);
	res = getContent(res);
	if (res == "OK") {
		serverStatus = 1; //在线
	}
	else {
		serverStatus = 0; //离线
	}
}

int main()
{
	beginLoader();
	initgraph(1200, 800, 1);
	gifCreater("Loading", 400, 0, 0, 300, 800, 0, 1);
	checkServerStatus();
	if (serverStatus && pdata.downloadFromServer()) { //从服务器上下载云端玩家数据
		pdata.updateToServer(); //如果有更改(本地比服务器数据高)，那么将本地数据上传一次给服务器
	}
	pdata.save(); //将程序中的内容同步到文件
	setbkcolor(RGB(0, 0, 0));
	LoadResources();

	double dur;
	clock_t start = clock(), end = clock();

	while (1)
	{
		showMenu_1();//画开始菜单
		cleardevice();

		/*下面是开头动画*/
		BeginBatchDraw();
		videoCreater("animation.1", 0, 0, HEIGHT, WIDTH, 0.01);
		while (1)
		{
			if (GetKeyState(0x45) < 0)//按下了e
			{
				Sleep(1000);
				break;
			}
		}
		videoCreater("animation.2", 0, 0, HEIGHT, WIDTH, 0.01);
		while (1)
		{
			if (GetKeyState(0x45) < 0)//按下了e
			{
				Sleep(1000);
				break;
			}
		}
		videoCreater("animation.3", 0, 0, HEIGHT, WIDTH, 0.01);
		EndBatchDraw();
		/*上面是开头动画*/


		hero.level = 1;
		Init();
		mciSendString(_T("open .\\music\\bgm.mp3 alias bkmusic"), NULL, 0, NULL);//打开背景音乐
		mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);  // 循环播放
		while (1)
		{
			show();//画
			updateWithoutInput();//更新 与输入无关
			updateWithInput();//更新 与输入有关
			/*下面用来测帧率*/
			end = clock();
			dur = (double)(end - start);
			if (tick % 10 == 0) printf("FPS: %f\n", 1 / (dur / CLOCKS_PER_SEC));
			start = clock();
			if (restart) break;
		}
		mciSendString(_T("close bkmusic"), NULL, 0, NULL);//关闭音乐
		restart = 0;
		Sleep(200);
	}
	_getch();
	closegraph();
	return 0;
}